package br.ujr.dynamicproxy;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

import javax.management.RuntimeErrorException;
import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;

public class TransacaoHandlerDynamicProxy implements InvocationHandler {

	private Object target;
	private EntityManager em;
	
	public TransacaoHandlerDynamicProxy(Object target, EntityManager em) {
		this.target = target;
		this.em = em;
	}
	
	@Override
	public Object invoke(Object obj, Method method, Object[] parameters) throws Throwable {
		Object retVal = null;
		
		Method  methodTarget    = this.getMethodTarget(method, parameters);
		boolean isTransactional = this.isTransactional(methodTarget);
		
		try {
			if ( isTransactional ) {
				System.out.println("Begin Transaction");
			}
			retVal = method.invoke(this.getTarget(), parameters);
			if ( isTransactional ) {
				System.out.println("Commit Transaction");
			}
		} catch (Exception e) {
			if ( isTransactional ) {
				System.out.println("RollBack Transaction");
			}
			e.printStackTrace();
		}
		
		return retVal;
	}

	private boolean isTransactional(Method method) {
		boolean retVal = false;
		TransacaoAtributo transacaoAtributo = method.getAnnotation(TransacaoAtributo.class);
		if ( transacaoAtributo.value() == TransacaoAtributoTipo.REQUER ) {
			retVal = true;
		}
		return retVal;
	}
	
	private Method getMethodTarget(Method method, Object[] parameters) throws NoSuchMethodException {
		Class[] parameterTypes = null;
		if ( parameters != null ) {
			int index = 0;
			parameterTypes = new Class[parameters.length];
			for (Object o : parameters) {
				parameterTypes[index++] = o.getClass();
			}
		}
		return this.getTarget().getClass().getMethod(method.getName(),parameterTypes);
	}

	public Object getTarget() {
		return target;
	}

	public void setTarget(Object target) {
		this.target = target;
	}

}
